#include "tlist.h"

TList::TList(void)
{
	first = NULL;
	last = NULL;
}

TList::TList(const TList &lc)
{
	first = NULL;
	last = NULL;

	if(!lc.IsEmpty())
	{
		TListNode *ln = lc.last;

		while(ln != NULL)
		{
			InsTop(ln->s);
			ln = ln->prev;
		}
	}
}

TList::~TList(void)
{
	if(!IsEmpty())
	{
		TListNode *ln = first;
        TListNode *tmp_n = NULL;

		while(ln != NULL)
		{
			tmp_n = ln->next;
			Erase(ln->s);
			ln = tmp_n;
		}
	}

	first = NULL;
	last = NULL;
}



TList &TList::operator=(const TList &lc)
{
	if(this != &lc)
	{
		TListNode *ln = first;

		if(!IsEmpty())
		{
			while(ln != NULL)
			{
				TListNode *tmp_n = ln->next;
				Erase(ln->s);
				ln = tmp_n;
			}
		}

		first = NULL;
		last = NULL;

		if(!lc.IsEmpty())
		{
			TListNode *ln = lc.last;

			while(ln != NULL)
			{
				InsTop(ln->s);
				ln = ln->prev;
			}
		}
	}

	return (*this);
}

bool TList::operator==(const TList &lc) const
{
	bool equal = true;

	if(!IsEmpty() && !lc.IsEmpty())
	{
		if(Length() == lc.Length())
		{
			TListNode *ln1, *ln2;

			ln1 = first;
			ln2 = lc.first;

			while(equal && ln1 != NULL && ln2 != NULL)
			{
				if(ln1->s != ln2->s)
				{
					equal = false;
				}
				else
				{
					ln1 = ln1->next;
					ln2 = ln2->next;
				}
			}
		}
		else
			equal = false;
	}
	else if((IsEmpty() && !lc.IsEmpty()) || (!IsEmpty() && lc.IsEmpty()))
		equal = false;

	return equal;
}

bool TList::operator!=(const TList &lc) const
{
	return !((*this) == lc);
}



ostream &operator<<(ostream &os, const TList &lc)
{
	os << LISTCOM_FIRST;

	if(!lc.IsEmpty())
	{
		TListNode *ln;

		ln = lc.first;

		while(ln != NULL)
		{
			if(ln != lc.first)
				os << LISTCOM_SEPARATION;

			os << ln->s;

			ln = ln->next;
		}

	}

	os << LISTCOM_LAST;

	return os;
}

bool TList::IsEmpty(void) const
{
	return (first == NULL);
}

/*
TSubtitle TList::Get(const TListPos &lp) const
{
	TSubtitle res;
	TListPos tlp;
	bool found = false;

	tln = first;

	if(!tlp.IsEmpty())
	{
		while(!found && !tlp.IsEmpty())
		{
			if(tlp == lp)
			{
				res = ln->s;
				found = true;
			}
			else
				tlp = tlp.Next();
		}
	}

	return res;
}



bool TList::Search(const TSubtitle &s) const
{
	bool found = false;
	TListPos lp;

	ln = first;

	while(!found && !lp.IsEmpty())
	{
		if(ln->s == s)
			found = true;
		else
			lp = lp.Next();
	}

	return found;
}

*/

int TList::Length(void) const
{
	int size = 0;
	TListNode *ln;

	ln = first;

	while(ln != NULL)
	{
		size++;
		ln = ln->next;
	}

	return size;
}

TListNode *TList::First(void) const
{
	return first;
}

TListNode *TList::Last(void) const
{
	return last;
}

TSubtitle &TList::Get(int id)
{
	TListNode *ln = first;

	while(ln != NULL && id > ln->s.GetID())
		ln = ln->next;

	if(ln != NULL && id == ln->s.GetID())
		return ln->s;
	else 
		return subt_error;
}

bool TList::Insert(const TSubtitle &s)
{
	bool res = false;

	if(IsEmpty())
	{
		if((first = new TListNode))
		{
			first->s = s;

			first->next = NULL;
			first->prev = NULL;

			last = first;
			res = true;
		}
	}
	else
	{
		TListNode *ln = first;

		while(ln != NULL && s.GetID() > ln->s.GetID())
			ln = ln->next;

		if(ln != NULL)
		{
			if(ln->s.GetID() == s.GetID())
			{
				ln->s = s;
				res = true;
			}
			else
				res = InsLeft(s, ln);
		}
		else
			res = InsTail(s);
	}
	
	return res;
}



bool TList::InsTop(const TSubtitle &s)
{
	bool res = false;

	if(IsEmpty())
	{
		if((first = new TListNode))
		{
			first->s = s;

			first->next = NULL;
			first->prev = NULL;

			last = first;
			res = true;
		}
	}
	else
		res = InsRight(s, first);

	return res;
}

bool TList::InsTail(const TSubtitle &s)
{
	bool res = false;

	if(IsEmpty())
	{
		if((last = new TListNode))
		{
			last->s = s;

			last->next = NULL;
			last->prev = NULL;

			first = last;
			res = true;
		}
	}
	else
		res = InsRight(s, last);

	return res;
}

bool TList::InsLeft(const TSubtitle &s, TListNode *ln)
{
	bool res = false;

	if(ln != NULL)
	{
		if(ln->prev != NULL)
		{
			TListNode *n_node = NULL;

			if((n_node = new TListNode))
			{
				TListNode *prev = ln->prev;
				ln->prev = n_node;

				n_node->s = s;
				n_node->next = ln;
				n_node->prev = prev;

				prev->next = n_node;

				res = true;
			}
		}
		else
		{
			TListNode *n_node = NULL;

			if((n_node = new TListNode))
			{
				ln->prev = n_node;

				n_node->s = s;
				n_node->next = ln;
				n_node->prev = NULL;

				first = n_node;

				res = true;
			}
		}
	}

	return res;
}

bool TList::InsRight(const TSubtitle &s, TListNode *ln)
{
	bool res = false;

	if(ln != NULL)
	{
		if(ln->next != NULL)
		{
			TListNode *next = ln->next;
			TListNode *n_node = NULL;

			if((n_node = new TListNode))
			{
				n_node->s = s;
				n_node->next = next;
				n_node->prev = ln;

                ln->next = n_node;
				next->prev = n_node;
				res = true;
			}
		}
		else
		{
			TListNode *n_node = NULL;

			if((n_node = new TListNode))
			{
				n_node->s = s;
				n_node->next = NULL;
				n_node->prev = ln;

                ln->next = n_node;
				last = n_node;
				res = true;
			}
		}
	}

	return res;
}

bool TList::Erase(const TSubtitle &s)
{
	bool found = false;
	TListNode *prev, *act, *next;

	act = first;

	while(!found && act != NULL )
	{
		TListNode *tmp_n = act->next;
		if(act->s == s)
		{
			found = true;
			if(act->prev == NULL)
			{
				if(act->next == NULL)
				{
					first = NULL;
					last = NULL;
				}
				else
				{
					next = act->next;
					next->prev = NULL;

					first = next;
				}
			}
			else
			{
				prev = act->prev;
				if(act->next == NULL)
				{
					prev->next = NULL;
					last = prev;
				}
				else
				{
					next = act->next;
					prev->next = next;
					next->prev = prev;
				}
			}
			delete act;
		}

		act = tmp_n;
	}
	return found;
}

bool TList::EraseAll(const TSubtitle &s)
{
	bool found = false;
	TListNode *prev, *act, *next;

	act = first;

	while(act != NULL)
	{
		TListNode *tmp_n = act->next;
		if(act->s == s)
		{
			found = true;
			if(act->prev == NULL)
			{
				if(act->next == NULL)
				{
					first = NULL;
					last = NULL;
				}
				else
				{
					next = act->next;
					next->prev = NULL;

					first = next;
				}
			}
			else
			{
				prev = act->prev;
				if(act->next == NULL)
				{
					prev->next = NULL;
					last = prev;
				}
				else
				{
					next = act->next;
					prev->next = next;
					next->prev = prev;
				}
			}
			delete act;
		}

		act = tmp_n;
	}

	return found;
}


bool TList::Erase(const TListNode *ln)
{
	bool res = false;

	if(ln != NULL)
	{
		res = true;
		Erase(ln->s);
	}

	return res;
}


// TListNode

TListNode::TListNode(void)
{
	prev = NULL;
	next = NULL;
}

TListNode::TListNode(const TListNode &ln)
{
	s = ln.s;

	if(ln.prev != NULL)
		prev = ln.prev;
	else
		prev = NULL;

	if(ln.next != NULL)
		next = ln.next;
	else
		next = NULL;

}

TListNode::~TListNode(void)
{
	prev = NULL;
	next = NULL;
}

TListNode &TListNode::operator=(const TListNode &ln)
{
	if(this != &ln)
	{
		s = ln.s;

		if(ln.prev != NULL)
			prev = ln.prev;
		else
			prev = NULL;

		if( ln.next != NULL )
			next = ln.next;
		else
			next = NULL;
	}

	return (*this);
}

